package com.nb.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.nb.dto.LoginDTO;
import com.nb.dto.RegisterDTO;
import com.nb.entity.User;
import com.nb.dto.*;
import com.nb.entity.*;
import com.nb.mapper.*;
import com.nb.service.UserService;
import com.nb.vo.LoginVO;
import com.nb.vo.RegisterVO;
import com.nb.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SysRoleUserMapper sysRoleUserMapper;

    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private LawyerMapper lawyerMapper;  // 注入律师Mapper
    @Autowired
    private RoleUserMapper roleUserMapper;

    public UserServiceImpl(RoleMapper roleMapper, RoleUserMapper roleUserMapper) {
        this.roleMapper = roleMapper;
        this.roleUserMapper = roleUserMapper;
    }

    @Override
    public List<User> list() {
        return userMapper.selectAll();
    }

    @Override
    public LoginVO login(LoginDTO loginDTO) {
        String username = loginDTO.getUsername();
        // 1.根据用户名查询用户
        QueryWrapper queryWrapper = QueryWrapper.create().eq("username", username);
        User user = userMapper.selectOneByQuery(queryWrapper);
        if (user == null) {
            throw new RuntimeException("用户名错误");
        }
        // 2.判断密码是否正确
        if (!user.getPassword().equals(DigestUtils.md5DigestAsHex(loginDTO.getPassword().getBytes()))) {
            throw new RuntimeException("密码错误");
        }
        // 3.判断用户状态是否正常
        if (user.getStatus() == 0) {
            throw new RuntimeException("用户已禁用");
        }

        LoginVO loginVO = new LoginVO();
        loginVO.setUser(user);

        // 4.生成token
        StpUtil.login(user.getId());
        String token = StpUtil.getTokenValue();
        loginVO.setToken(token);

        return loginVO;
    }

    @Override
    @Transactional // 确保多表操作原子性
    public RegisterVO register(RegisterDTO registerDTO) {
        // 1. 验证密码一致性
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new RuntimeException("两次密码输入不一致");
        }

        // 2. 唯一性校验
        QueryWrapper queryWrapper = QueryWrapper.create()
                .eq("username", registerDTO.getUsername());
        if (userMapper.selectOneByQuery(queryWrapper) != null) {
            throw new RuntimeException("用户名已存在");
        }

        queryWrapper = QueryWrapper.create().eq("phone", registerDTO.getPhone());
        if (userMapper.selectOneByQuery(queryWrapper) != null) {
            throw new RuntimeException("该手机号已注册");
        }

        queryWrapper = QueryWrapper.create().eq("id_card", registerDTO.getIdCard());
        if (userMapper.selectOneByQuery(queryWrapper) != null) {
            throw new RuntimeException("该身份证号已注册");
        }

        // 3. 插入用户表（sys_user）
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(DigestUtils.md5DigestAsHex(registerDTO.getPassword().getBytes())); // 密码加密
        user.setPhone(registerDTO.getPhone());
        user.setEmail(registerDTO.getEmail());
        user.setRealName(registerDTO.getRealName());
        user.setIdCard(registerDTO.getIdCard());
        user.setUserType("USER"); // 固定为普通用户
        user.setStatus(1); // 启用状态
        user.setIsDelete(0); // 未删除
        user.setCreatedBy("system");
        user.setCreatedTime(LocalDateTime.now());
        user.setUpdatedTime(LocalDateTime.now());
        userMapper.insertSelective(user);
        Long userId = user.getId(); // 获取自增用户ID

        // 4. 关联用户角色（sys_role_user）
        // 参考SQL数据，普通用户角色ID为2（SELECT id FROM sys_role WHERE name = 'USER'）
        SysRoleUser roleUser = new SysRoleUser();
        roleUser.setUserId(userId);
        roleUser.setRoleId(2L); // 普通用户角色ID
        roleUser.setCreatedTime(new Date());
        sysRoleUserMapper.insert(roleUser);

        // 5. 自动登录生成token
        StpUtil.login(userId);
        String token = StpUtil.getTokenValue();

        // 6. 构建返回结果
        RegisterVO registerVO = new RegisterVO();
        registerVO.setUserId(userId);
        registerVO.setUsername(user.getUsername());
        registerVO.setToken(token);
        registerVO.setMessage("普通用户注册成功");

        return registerVO;
    }
    // 律师注册方法
    @Transactional
    public RegisterVO registerLawyer(LawyerRegisterDTO registerDTO) {
        // 1. 验证密码一致性
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new RuntimeException("两次密码输入不一致");
        }

        // 2. 唯一性校验
        QueryWrapper queryWrapper = QueryWrapper.create()
                .eq("username", registerDTO.getUsername());
        if (userMapper.selectOneByQuery(queryWrapper) != null) {
            throw new RuntimeException("用户名已存在");
        }

        // 校验律师执照号唯一性
        queryWrapper = QueryWrapper.create().eq("license_no", registerDTO.getLicenseNo());
        if (lawyerMapper.selectOneByQuery(queryWrapper) != null) {
            throw new RuntimeException("该律师执照号已注册");
        }

        // 3. 插入用户表（sys_user）
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(DigestUtils.md5DigestAsHex(registerDTO.getPassword().getBytes()));
        user.setPhone(registerDTO.getPhone());
        user.setEmail(registerDTO.getEmail());
        user.setRealName(registerDTO.getRealName());
        user.setIdCard(registerDTO.getIdCard());
        user.setUserType("LAWYER");  // 标识为律师用户
        user.setStatus(1);
        user.setIsDelete(0);
        user.setCreatedBy("system");
        user.setCreatedTime(LocalDateTime.now());
        user.setUpdatedTime(LocalDateTime.now());
        userMapper.insertSelective(user);
        Long userId = user.getId();

        // 4. 关联律师角色（角色ID为3）
        SysRoleUser roleUser = new SysRoleUser();
        roleUser.setUserId(userId);
        roleUser.setRoleId(3L);  // 律师角色ID
        roleUser.setCreatedTime(new Date());
        sysRoleUserMapper.insert(roleUser);

        // 5. 插入律师信息表
        Lawyer lawyer = new Lawyer();
        lawyer.setUserId(userId);
        lawyer.setLicenseNo(registerDTO.getLicenseNo());
        lawyer.setSpecialty(registerDTO.getSpecialty());
        lawyer.setYearsOfPractice(registerDTO.getYearsOfPractice());
        lawyer.setIntroduction(registerDTO.getIntroduction());
        lawyer.setServiceArea(registerDTO.getServiceArea());
        lawyer.setIsCertified(0);  // 初始未认证
        lawyer.setCreateTime(LocalDateTime.now());
        lawyer.setUpdateTime(LocalDateTime.now());
        lawyerMapper.insert(lawyer);

        // 6. 生成登录token
        StpUtil.login(userId);
        String token = StpUtil.getTokenValue();

        // 7. 构建返回结果
        RegisterVO registerVO = new RegisterVO();
        registerVO.setUserId(userId);
        registerVO.setUsername(user.getUsername());
        registerVO.setToken(token);
        registerVO.setMessage("律师注册成功，等待审核");

        return registerVO;
    }

    @Transactional
    @Override
    public Long createUser(CreateUserDTO createUserDTO) {
        Boolean isLawyer = false;
        String password = createUserDTO.getPassword();
        String encode = DigestUtils.md5DigestAsHex(password.getBytes());
        createUserDTO.setPassword(encode);
        User user = new User();
        BeanUtils.copyProperties(createUserDTO, user);
        user.setCreatedBy("admin");
        user.setCreatedTime(LocalDateTime.now());

        userMapper.insertSelective(user);

        Long[] roleIds = createUserDTO.getRoleIds();
        if (roleIds != null && roleIds.length > 0) {
            List<RoleUser> list = new LinkedList<>();
            for (Long roleId : roleIds) {
                if (roleId == 3) {
                    isLawyer = true;
                }
                RoleUser roleUser = new RoleUser();
                roleUser.setUserId(user.getId());
                roleUser.setRoleId(roleId);
                roleUser.setCreatedTime(LocalDateTime.now());
                list.add(roleUser);
            }
            roleUserMapper.insertBatch(list);
        }

        //添加律师
        if (isLawyer) {
            // 律师用户，关联律师角色
            Lawyer lawyer = new Lawyer();
            lawyer.setUserId(user.getId());
            lawyer.setCreateTime(LocalDateTime.now());
            lawyerMapper.insertSelective(lawyer);
        }
        return user.getId();
    }

    @Override
    public User getUserById(Long id) {
        if (id == null || id <= 0) {
            log.warn("查询用户ID非法: {}", id);
            return null;
        }

        // 使用整数常量作为条件，与数据库tinyint类型完全匹配
        QueryWrapper queryWrapper = QueryWrapper.create()
                .eq(User::getId, id);

        return userMapper.selectOneByQuery(queryWrapper);
    }

    @Override
    public User getByUsername(String username) {
        if (username == null || username.trim().isEmpty()) {
            log.warn("查询用户名为空");
            return null;
        }

        QueryWrapper queryWrapper = QueryWrapper.create()
                .eq(User::getUsername, username)
                .eq(User::getIsDelete, 0) // 未删除
                .eq(User::getStatus, 1); // 启用状态

        return userMapper.selectOneByQuery(queryWrapper);
    }

    @Override
    @Transactional
    public void updateUser(UpdateUserDTO updateUserDTO) {

        User user = userMapper.selectOneById(updateUserDTO.getId());

        user.setUsername(updateUserDTO.getUsername());
        user.setRealName(updateUserDTO.getRealName());
        user.setEmail(updateUserDTO.getEmail());
        user.setPhone(updateUserDTO.getPhone());
        user.setDeptId(updateUserDTO.getDeptId());
        user.setIdCard(updateUserDTO.getIdCard());
        user.setUpdatedTime(LocalDateTime.now());
        //更新用户基本信息
        userMapper.update(user,false);

        Long[] roleIds = updateUserDTO.getRoleIds();

        if (roleIds != null && roleIds.length > 0) {
            //删除用户角色
            QueryWrapper queryWrapper = QueryWrapper.create().eq("user_id", updateUserDTO.getId());
            sysRoleUserMapper.deleteByQuery(queryWrapper);
            //根据角色数组添加用户角色
            List<SysRoleUser> list = new LinkedList<>();
            for (Long roleId : roleIds) {
                SysRoleUser roleUser = new SysRoleUser();
                roleUser.setUserId(updateUserDTO.getId());
                roleUser.setRoleId(roleId);
                roleUser.setCreatedTime(new Date());
                list.add(roleUser);
            }
            sysRoleUserMapper.insertBatch(list);
        }
    }

    @Override
    public Page<UserVO> getUserPage(UserQueryDTO queryDTO) {
        Page<UserVO> page = Page.of(queryDTO.getPageNum(), queryDTO.getPageSize());
        return userMapper.searchPage(page, queryDTO);

    }

    @Override
    public void resetPassword(ResetPasswordDTO resetPasswordDTO) {
        Long id = resetPasswordDTO.getUserId();
        String newPassword = resetPasswordDTO.getNewPassword();
        // 2. 使用BCrypt加密新密码（与创建用户时的加密方式一致）
        String password = DigestUtils.md5DigestAsHex(newPassword.getBytes());
        userMapper.updatePasswordById(id,password);

    }

    @Override
    @Transactional
    public void deleteUser(Long id) {
        //TODO删除律师
        List<Long> roleIdList = roleMapper.selectRoleIdListByUserId(id);
        //律师角色id为3，判断是不是律师
        if (roleIdList.contains(3L)) {
            //根据用户id删除律师信息
            lawyerMapper.deleteByQuery(QueryWrapper.create().eq("user_id", id));
        }
        userMapper.deleteById(id);
    }

    @Override
    public UserVO getUserDetail(Long id) {

        // 1. 查询用户基本信息（未被删除）
        User user = getUserById(id);
        if (user == null) {
            log.warn("查询用户详情失败，用户不存在或已被删除: {}", id);
            return null;
        }

        // 2. 转换为UserVO并复制基本属性
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        userVO.setUserId(user.getId());
        userVO.setDeptId(user.getDeptId());

        // 3. 查询部门信息
        if (user.getDeptId() != null) {
            Dept dept = deptMapper.selectOneById(user.getDeptId());
            if (dept != null) {
                userVO.setDeptName(dept.getName());
            }
        }

        // 4. 查询角色名称和id
        List<String> roleNameList = roleMapper.selectRoleNameListByUserId(id);
        if (roleNameList != null && !roleNameList.isEmpty()) {
            userVO.setRoleNames(roleNameList);
        }
        List<Long> roleIdList = roleMapper.selectRoleIdListByUserId(id);
        if (roleIdList != null && !roleIdList.isEmpty()) {
            userVO.setRoleIds(roleIdList);
        }

        return userVO;
    }

    @Override
    public void updateStatus(StatusDTO statusDTO) {
        Long id = statusDTO.getId();
        Integer status = statusDTO.getStatus();
        User user = new User();
        user.setId(id);
        user.setStatus(status);
        userMapper.update(user);
    }
    @Override
    @Transactional
    public void assignRoles(AssignRolesDTO dto) {
        // 1. 校验用户是否存在
        User user = userMapper.selectOneById(dto.getUserId());
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 2. 校验角色有效性（必须存在且未被删除）
        if (dto.getRoleIds() != null && !dto.getRoleIds().isEmpty()) {
            for (Long roleId : dto.getRoleIds()) {
                Role role = roleMapper.selectOneById(roleId);
                if (role == null || role.getIsDelete() == 1) {
                    throw new RuntimeException("角色ID " + roleId + " 不存在或已被删除");
                }
            }
        }

        // 3. 删除用户原有的所有角色关联
        QueryWrapper queryWrapper = QueryWrapper.create()
                .eq("user_id", dto.getUserId());
        sysRoleUserMapper.deleteByQuery(queryWrapper);

        // 4. 插入新的角色关联
        if (dto.getRoleIds() != null && !dto.getRoleIds().isEmpty()) {
            List<SysRoleUser> list = new LinkedList<>();
            for (Long roleId : dto.getRoleIds()) {
                SysRoleUser roleUser = new SysRoleUser();
                roleUser.setUserId(dto.getUserId());
                roleUser.setRoleId(roleId);
                roleUser.setCreatedTime(new Date());
                list.add(roleUser);
            }
            sysRoleUserMapper.insertBatch(list);
        }

        // 5. 记录操作日志（示例：使用日志框架）
        log.info("用户角色分配成功: 用户ID={}, 分配角色={}", dto.getUserId(), dto.getRoleIds());

        // 6. 刷新用户权限缓存（关键！避免权限不一致）
        // 清除当前用户的权限缓存（可选：只清除该用户，或全部）
        // 示例：使用 Sa-Token 的 token 清除机制
        StpUtil.logout(dto.getUserId()); // 强制登出，触发重新登录时加载新权限
        // 或者手动刷新权限（如果使用 Redis 缓存）
        // authService.clearUserPermissionsCache(dto.getUserId());
    }
}
